/*
 * Copyright (c) 2024 Black Sesame Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef F_HTML_GENERATOR_H
#define F_HTML_GENERATOR_H
#include "AbstractGenerator.h"
#include "model/FFactory.h"
#include "model/FModelManager.h"
#include <fstream>
#include <iostream>
namespace BstIdl
{
class HTMLGenerator : public AbstractGenerator
{
private:
    std::string t_model = R"(<!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <style>
                h2 ,h3 ,h4 ,h5 ,h6,p {color: #333;}
                h1 {color: #2f6d7c;}
                em,b {color: #2f6d7c;}
                hr{border:.5px solid #C1DAD7;}
                table {
                    border-collapse: collapse;
                    border-spacing: 0;
                    empty-cells: show;
                    border: 1px solid #cbcbcb;
                }
                td a{ color: #2f6d7c;}
                table th {
                    color: #2f6d7c;
                    border-right: 1px solid #C1DAD7;
                    border-bottom: 1px solid #C1DAD7;
                    border-top: 1px solid #C1DAD7;
                    letter-spacing: 2px;
                    text-transform: uppercase;
                    text-align: left;
                    padding: 6px 6px 6px 12px;
                    background: #CAE8EA no-repeat;
                }
                td {
                    border-right: 1px solid #C1DAD7;
                    border-bottom: 1px solid #C1DAD7;
                    background: #fff;
                    padding: 6px 6px 6px 12px;
                    color: #2f6d7c;
                    min-width: 100px;
                }
                tr:odd {
                    background-color: #f2f2f2;
                }
            </style>
        </head>
            <body>
		        <h1>Package: NAME</h1>
                INTERFACES
                TYPECOLLECTIONS
                <br><hr>
                <em>Generated by com.bst.os.tools.idl.HTMLGenerator</em>
            </body>
        </html>
        )";
    std::string t_interface = R"(<h2>Interface: NAME</h2>
            VERSION
            COMMENT
            ATTRIBUTES
            METHODS
            BROADCASTS
            TYPES)";
    std::string t_type_collection = R"(<h2>Type Collection: NAME</h2>
            VERSION
            COMMENT
            TYPES)";
    std::string t_interface_version = R"(<h3>Version: VERSION_MAJOR.VERSION_MINOR</h3>)";
    std::string t_attribute = R"(<h3>Attributes</h3>
            <table border=1>
            <tr><th>Type</th><th>Name</th><th>Comment</th></tr>
            ATTRIBUTE_ITEM
            </table>
            )";
    std::string t_attribute_item = R"(<tr><td>TYPE</td><td><b>NAME</b></td><td>COMMENT</td></tr>)";
    std::string t_method = R"(<h3>Methods</h3>
        METHOD_ITEM)";
    std::string t_method_item = R"(<h4>NAME</h4>
        COMMENT
        METHOD_GEN)";
    std::string t_broadcast = R"(<h3>Broadcasts</h3>
        BROADCAST_ITEM)";
    std::string t_broadcast_item = R"(<h4>NAME</h4>
        COMMENT
        BROADCAST_GEN)";
    std::string t_types = R"(<h3>TYPE</h3>
        COMMENT
        TYPE_GEN)";
    std::string t_method_gen = R"(
        <table border=1>
		<tr><th>Dir</th><th>Type</th><th>Name</th><th>Comment</th></tr>
        INARGS
        OUTARGS
        </table>
        )";
    std::string t_error_enum = R"(<tr><td>error</td><td>ERROR_ENUM_LINK</td><td></td><td></td></tr>)";
    std::string t_error_base = R"(<tr><td>error</td><td>ERROR_EXTENDS</td><td></td><td></td></tr>)";
    std::string t_error_enumrators = R"(<tr><td>error</td><td></td>
        <td>NAME</td>
        <td>COMMENT</td></tr>)";
    std::string t_broadcast_gen = R"(<table border=1>
		<tr><th>Dir</th><th>Type</th><th>Name</th><th>Comment</th></tr>
		OUTARGS
		</table>)";
    std::string t_argument = R"(<tr><td>TAG</td><td>TYPE</td><td>NAME</td><td>COMMENT</td></tr>)";
    std::string t_types_gen = R"(<table border=1>
		<tr><th>Type name</th><th>Comment</th><th>Definition</th></tr>
		TYPE_ITEM
		</table>)";
    std::string t_type_item = R"(<tr>
				<td><a name=type_NAME>NAME</a>BASE</td>
				<td>COMMENT</td>
				<td>GENERATE_DEFINITION</td>
			</tr>)";
    std::string t_extends = R"( extends EXTEND)";
    std::string t_array_type_def = R"( Array of ELEMENT_TYPE)";
    std::string t_compound_type_def = R"(<table border=1>
			COMPOUND_TYPE_ITEM
		</table>)";
    std::string t_compound_type_item = R"(<tr>
					<td>NAME</td>
					<td>TYPE</td>
					<td>COMMENT</td>
				</tr>)";
    std::string t_enum_type_def = R"(<table border=1>
			ENUMERATORS
		</table>)";
    std::string t_enumrator = R"(<tr>
					<td>NAME</td>
					<td>VALUE</td>
					<td>COMMENT</td>
				</tr>)";
    std::string t_integerInterval_def = R"(<td>Upper bound:UPPER</td><td>Lower Bound:LOWER</td>)";
    std::string t_map_type_def = R"(Map KEY to VALUE)";
    std::string t_type_def_def = R"(Actual type : ACTUALTYPE)";
    std::string t_type_label_linked = R"(<a href="#type_NAME">NAME</a>)";
    std::string t_single_line_comment = R"(<b> TYPE_LITERAL </b> : <em> COMMENT </em>)";
    std::string t_single_line_comment_des = R"(<em> COMMENT </em>)";
    std::string t_multi_line_comment = R"(<tr><td><b>TYPE_LITERAL</b></td><td><em>COMMENT</em></td></tr>)";
    std::string t_multi_line_comment_des = R"(<tr><td colspan=2><em>COMMENT</em></td></tr>)";

public:
    HTMLGenerator(const std::string &destDir = std::string()) : AbstractGenerator(destDir)
    {
    }
    ~HTMLGenerator() = default;
    HTMLGenerator(const HTMLGenerator &) = default;
    HTMLGenerator(HTMLGenerator &&) noexcept = default;
    HTMLGenerator &operator=(const HTMLGenerator &) = default;
    HTMLGenerator &operator=(HTMLGenerator &&) = default;
    bool generate() override;
    std::string makeModel(const std::shared_ptr<FModel> &model);
    std::string makeInterfaces(const std::list<std::shared_ptr<FInterface>> &interfaces);
    std::string makeInterface(const std::shared_ptr<FInterface> &interface);
    std::string makeTypeCollections(const std::list<std::shared_ptr<FTypeCollection>> &typeCollections);
    std::string makeTypeCollection(const std::shared_ptr<FTypeCollection> &typeCollection);
    std::string makeAttributes(const std::list<std::shared_ptr<FAttribute>> &attribute);
    std::string makeAttribute(const std::shared_ptr<FAttribute> &attribute);
    std::string makeMethods(const std::list<std::shared_ptr<FMethod>> &methods);
    std::string makeMethod(const std::shared_ptr<FMethod> &method);
    std::string makeMethodComment(const std::shared_ptr<FMethod> &method);
    std::string makeBroadcasts(const std::list<std::shared_ptr<FBroadcast>> &broadcasts);
    std::string makeBroadcast(const std::shared_ptr<FBroadcast> &broadcast);
    std::string makeError(const std::shared_ptr<FEnumerationType> &errors);
    std::string makeErrorEnumerator(const std::shared_ptr<FEnumerationType> &errorEnum);
    std::string makeArguments(const std::list<std::shared_ptr<FArgument>> &arg, const std::string &tag);
    std::string makeTypes(const std::list<std::shared_ptr<FType>> &types);
    std::string makeTypesItem(const std::shared_ptr<FType> type);
    std::string makeCompound(const std::shared_ptr<FCompoundType> &compount);
    std::string makeCompoundItem(const std::shared_ptr<FField> &element);
    std::string makeEnumration(const std::shared_ptr<FEnumerationType> &enumeration);
    std::string makeEnumrator(const std::shared_ptr<FEnumerator> &enumerator);
    std::string makeExtend(const std::shared_ptr<FType> &type);
    std::string makeLabelLink(const std::shared_ptr<FTypeRef> &type);
    std::string makeLabelLink(const std::shared_ptr<FType> &type);
    std::string makeComment(const std::shared_ptr<FModelElement> &element, bool paragraph);
    void makeSingleLineComment(const std::shared_ptr<BstIdl::FAnnotation> &annotation, std::string &single_comment,
                               bool des);
};

} // namespace BstIdl
#endif